package photoEffects
{
	import __AS3__.vec.Vector;
	
	import com.gskinner.utils.Rndm;
	import com.suckatmath.detector.Detector;
	import com.suckatmath.detector.classifier.HaarClassifier;
	
	import flash.display.Bitmap;
	import flash.display.Shader;
	import flash.filters.ShaderFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.ByteArray;
	
	import mx.controls.Alert;
	
	import org.casalib.events.ProcessEvent;
	
	public class DistortFaceEffect extends PhotoEffect
	{
		public function DistortFaceEffect()
		{
			super();
		}
		
		public static const NAME:String = "Distorted Face";
		
		/**
		 * Apply the effect on a Bitmap. When the apply is finished, a ProcessEvent.COMPLETE is dispatched.
		 * @param bitmap The source Bitmap.
		 * @param callBack A function that accept a Bitmap object. Called when apply is finished.
		 */
		public override function applyOn(bitmap:Bitmap, callBack:Function = null):void
		{	
			_workingBitmap = new Bitmap(bitmap.bitmapData.clone());
			
			var ran:Rndm = new Rndm(bitmap.bitmapData.getPixel(100,100) + bitmap.bitmapData.getPixel(200,200) - bitmap.bitmapData.getPixel(300,300));
			var xml:XML = XML(new haarcascade_frontalface_alt());
			var classifier:HaarClassifier = HaarClassifier.fromXML(xml.*.(@type_id == "opencv-haar-classifier")[0]);
			var detector:Detector = new Detector(classifier, int.MAX_VALUE , _workingBitmap.width/5); //new Detector(classifier, 1, 30);
			detector.bitmap = bitmap.bitmapData.clone()
			var faceRects:Vector.<Rectangle> = detector.detect();
			
			if(faceRects && faceRects.length > 0){
				for (var i:int = 0 ; i< faceRects.length ; i++){
					var s:Shader = new Shader(new ShaderClass_twirl() as ByteArray);
					s.data.center.value = [faceRects[i].x + faceRects[i].width*0.5, faceRects[i].y + faceRects[i].height*0.5];
					s.data.radius.value = [Math.min(faceRects[i].width, faceRects[i].height)*0.2];
					s.data.twirlAngle.value = [ran.sign()*ran.float(60,140)];
					shaderFilter_twirl = new ShaderFilter(s);
					_workingBitmap.bitmapData.applyFilter(_workingBitmap.bitmapData,_workingBitmap.bitmapData.rect,new Point(),shaderFilter_twirl);
				}
			} else {
				Alert.show("No face is detected! So no effect is applied to the photo!");
			}
			
			
			/*
			var graphic:Shape = new Shape();
			graphic.graphics.lineStyle(1,0xFF0000);
			for (var i:uint = 0 ; i < faceRects.length; i++){
				graphic.graphics.drawRect(faceRects[i].x, faceRects[i].y, faceRects[i].width, faceRects[i].height);
			}
			_workingBitmap.bitmapData.draw(graphic);*/
			
			
			_resultBitmap = _workingBitmap;
			_workingBitmap = null;
			
			dispatchEvent(new ProcessEvent(ProcessEvent.COMPLETE));
			
			if(callBack != null){
				callBack(_resultBitmap);
			}
		}
		
		[Embed(source="../../classifiers/haarcascade_frontalface_alt.xml",mimeType = "application/octet-stream")]
		private static var haarcascade_frontalface_alt:Class;
		
		[Embed(source="../../pb/twirl.pbj", mimeType="application/octet-stream")]
		private static var ShaderClass_twirl:Class;
		private static var shaderFilter_twirl:ShaderFilter;
		
	}
}